package capstoneproject.dudiachi.Main;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import capstoneproject.dudiachi.Controller.ConvertBetweenSonarLunar;
import capstoneproject.dudiachi.Controller.FestivalManager;
import capstoneproject.dudiachi.Model.Festival;
import capstoneproject.dudiachi.Main.R;

public class FestivalCalendarGridCellAdapter extends BaseAdapter implements OnClickListener {

	private FestivalManager _festivalManager;
	private final Context _context;
	private final List<String> list;
	private static final int DAY_OFFSET = 1;
	private final String[] weekdays = new String[] { "Sun", "Mon", "Tue",
			"Wed", "Thu", "Fri", "Sat" };
	private final String[] months = { "January", "February", "March", "April",
			"May", "June", "July", "August", "September", "October",
			"November", "December" };
	private final int[] daysOfMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	private final int month, year;
	private int currentDayOfMonth, currentMonth, currentYear;
	private int currentWeekDay;
	private Button gridcell;
	private TextView lunarDay;
	private Map<String, Integer> eventsPerMonthMap;
	private List<String> day;

	public FestivalCalendarGridCellAdapter(Context context, int textViewResourceId,
			int date, int month, int year, FestivalManager festivalManager) {
		super();
		this._festivalManager = festivalManager;
		this._context = context;
		this.list = new ArrayList<String>();
		this.month = month;
		this.year = year;
		
		Calendar calendar = Calendar.getInstance();
		setCurrentDayOfMonth(calendar.get(Calendar.DAY_OF_MONTH));
		setCurrentMonth(calendar.get(Calendar.MONTH));
		setCurrentYear(calendar.get(Calendar.YEAR));
		setCurrentWeekDay(calendar.get(Calendar.DAY_OF_WEEK));

		// Print Month
		printMonth(this.month, this.year);

		// eventsPerMonthMap = numberOfEventsPerDay(dd, mm, yy);
	}

	private String getMonthAsString(int i) {
		return months[i];
	}

	private String getWeekDayAsString(int i) {
		return weekdays[i];
	}

	private int getNumberOfDaysOfMonth(int i) {
		return daysOfMonth[i];
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return list.size();
	}

	@Override
	public String getItem(int position) {
		// TODO Auto-generated method stub
		return list.get(position);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}

	private Map<String, Integer> numberOfEventsPerDayMap(int dd, int mm, int yy) {
		Map<String, Integer> map = new HashMap<String, Integer>();
		
		
		String eventCheckDate = dd + ""; 
		String dateInArray = "";
		
		ArrayList<Festival> eventByDate = _festivalManager.searchByDate(dd, mm, yy);
			if (eventByDate.size() != 0) {
				if (map.containsKey(dateInArray)) {
					int value = (int) map.get(dateInArray) + 1;
					map.put(eventCheckDate, value);
				} else {
					map.put(eventCheckDate, 1);
				}
			}

		return map;
	}

	private void printMonth(int mm, int yy) {

		// The number of days to leave blank at
		// the start of this month.

		int trailingSpaces = 0;
		// int leadSpaces = 0;
		int daysInMonth;
		int daysInPrevMonth = 0;
		int prevMonth = 0;
		int prevYear = 0;
		int nextMonth = 0;
		int nextYear = 0;
		int currentMonth = mm - 1;
		// String currentMonthName = getMonthAsString(currentMonth);
		daysInMonth = getNumberOfDaysOfMonth(currentMonth);

		// Gregorian Calendar : MINUS 1, set to FIRST OF MONTH
		GregorianCalendar cal = new GregorianCalendar(yy, currentMonth, 1);

		if (currentMonth == 11) {
			prevMonth = currentMonth - 1;
			daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
			nextMonth = 0;
			prevYear = yy;
			nextYear = yy + 1;

		} else if (currentMonth == 0) {
			prevMonth = 11;
			prevYear = yy - 1;
			nextYear = yy;
			daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
			nextMonth = 1;

		} else {
			prevMonth = currentMonth - 1;
			nextMonth = currentMonth + 1;
			nextYear = yy;
			prevYear = yy;
			daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);

		}

		// Compute how much to leave before before the first day of the month.
		// getDay() returns 0 for Sunday.
		int currentWeekDay = cal.get(Calendar.DAY_OF_WEEK);
		trailingSpaces = currentWeekDay - 1;

		if (cal.isLeapYear(cal.get(Calendar.YEAR))) {
			if (mm == 2) {
				++daysInMonth;
			}
			if (mm == 3) {
				++daysInPrevMonth;
			}
		}

		// Trailing Month days
		for (int i = 0; i < trailingSpaces; i++) {
			Calendar calendar = new GregorianCalendar(prevYear, prevMonth,
					(daysInPrevMonth - trailingSpaces + DAY_OFFSET) + i);
			int date = calendar.get(Calendar.DAY_OF_WEEK);

			if (date == 7) {
				list.add(String.valueOf((daysInPrevMonth - trailingSpaces + DAY_OFFSET) + i)+ "-LtGREEN"+ "-"+ getMonthAsString(prevMonth)+ "-"+ prevYear + "-" + getWeekDayAsString(date - 1));
			} else if (date == 1) {
				list.add(String.valueOf((daysInPrevMonth - trailingSpaces + DAY_OFFSET)+ i)+ "-LtRED"+ "-"+ getMonthAsString(prevMonth)+ "-"+ prevYear + "-" + getWeekDayAsString(date - 1));
			} else {
				list.add(String.valueOf((daysInPrevMonth - trailingSpaces + DAY_OFFSET)+ i)+ "-GRAY"+ "-"+ getMonthAsString(prevMonth)+ "-"+ prevYear + "-" + getWeekDayAsString(date - 1));
			}

		}

		// Current Month Days
		for (int i = 1; i <= daysInMonth; i++) {
			Calendar calendar = new GregorianCalendar(yy, currentMonth, i);
			int date = calendar.get(Calendar.DAY_OF_WEEK);
			if (i == getCurrentDayOfMonth()) {
				if (date == 7) {
					list.add(String.valueOf(i) + "-GREEN" + "-"+ getMonthAsString(currentMonth) + "-" + yy + "-"+ getWeekDayAsString(date - 1));
				} else if (date == 1) {
					list.add(String.valueOf(i) + "-RED" + "-"+ getMonthAsString(currentMonth) + "-" + yy + "-"+ getWeekDayAsString(date - 1));
				} else {
					list.add(String.valueOf(i) + "-BLUE" + "-"+ getMonthAsString(currentMonth) + "-" + yy + "-"+ getWeekDayAsString(date - 1));

				}
			} else {
				if (date == 7) {
					list.add(String.valueOf(i) + "-GREEN" + "-"+ getMonthAsString(currentMonth) + "-" + yy + "-"+ getWeekDayAsString(date - 1));
				} else if (date == 1) {
					list.add(String.valueOf(i) + "-RED" + "-"+ getMonthAsString(currentMonth) + "-" + yy + "-"+ getWeekDayAsString(date - 1));
				} else {
					list.add(String.valueOf(i) + "-BLACK" + "-"+ getMonthAsString(currentMonth) + "-" + yy + "-"+ getWeekDayAsString(date - 1));
				}
			}
		}

		// Leading Month days
		for (int i = 0; i < list.size() % 7; i++) {
			Calendar calendar = new GregorianCalendar(nextYear, nextMonth, i + 1);
			int date = calendar.get(Calendar.DAY_OF_WEEK);
			if (date == 7) {
				list.add(String.valueOf(i + 1) + "-LtGREEN" + "-" + getMonthAsString(nextMonth) + "-" + nextYear + "-"+ getWeekDayAsString(date - 1));
			} else if (date == 1) {
				list.add(String.valueOf(i + 1) + "-LtRED" + "-" + getMonthAsString(nextMonth) + "-" + nextYear + "-"+ getWeekDayAsString(date - 1));
			} else {
				list.add(String.valueOf(i + 1) + "-GRAY" + "-" + getMonthAsString(nextMonth) + "-" + nextYear + "-"+ getWeekDayAsString(date - 1));
			}
		}
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {

		int dd, mm = 0, yy;
		View row = convertView;

		if (row == null) {
			LayoutInflater inflater = (LayoutInflater) _context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			row = inflater.inflate(R.layout.calendar_day_gridcell, parent, false);

		}


		lunarDay = (TextView) row.findViewById(R.id.lunarDay);

		// Get a reference to the Day gridcell
		gridcell = (Button) row.findViewById(R.id.calendar_day_gridcell);
		
		
		gridcell.setOnClickListener(this);

		// ***
		String[] listGridCellCal = list.get(position).split("-");

		// set gridview for Lunar Day ***
		ConvertBetweenSonarLunar convertSL = new ConvertBetweenSonarLunar();

		if (listGridCellCal[2].equals("January")) {
			mm = 1;
		}
		if (listGridCellCal[2].equals("February")) {
			mm = 2;
		}
		if (listGridCellCal[2].equals("March")) {
			mm = 3;
		}
		if (listGridCellCal[2].equals("April")) {
			mm = 4;
		}
		if (listGridCellCal[2].equals("May")) {
			mm = 5;
		}
		if (listGridCellCal[2].equals("June")) {
			mm = 6;
		}
		if (listGridCellCal[2].equals("July")) {
			mm = 7;
		}
		if (listGridCellCal[2].equals("August")) {
			mm = 8;
		}
		if (listGridCellCal[2].equals("September")) {
			mm = 9;
		}
		if (listGridCellCal[2].equals("October")) {
			mm = 10;
		}
		if (listGridCellCal[2].equals("November")) {
			mm = 11;
		}
		if (listGridCellCal[2].equals("December")) {
			mm = 12;
		}
		dd = Integer.parseInt(listGridCellCal[0]);
		yy = Integer.parseInt(listGridCellCal[3]);
		int[] convert = convertSL.Solar2Lunar(dd, mm, yy);
		int k = convert[0];

		if (convert[0] == 1) {
			lunarDay.setText("" + k + "/" + convert[1]);
		} else {
			lunarDay.setText("" + k);
		}

		// Set the Day GridCell ***
		gridcell.setText(listGridCellCal[0]);
		gridcell.setTag(dd + "/" + mm + "/" + yy);

		day = new ArrayList<String>();
		day.add(dd + "-" + mm);

		
		

		// color of the previous month's day
		if (listGridCellCal[1].equals("GRAY")) {
			gridcell.setTextColor(Color.LTGRAY);
			lunarDay.setTextColor(Color.LTGRAY);

		}
		if (listGridCellCal[1].equals("LtRED")) {
			gridcell.setTextColor(_context.getResources().getColor(R.color.ltred));
			lunarDay.setTextColor(_context.getResources().getColor(R.color.ltred));
		}
		if (listGridCellCal[1].equals("LtGREEN")) {
			gridcell.setTextColor(_context.getResources().getColor(R.color.ltgreen));
			lunarDay.setTextColor(_context.getResources().getColor(R.color.ltgreen));
		}
		
		// color of the current month's day
		if (listGridCellCal[1].equals("BLACK")) {
			gridcell.setTextColor(Color.BLACK);
			lunarDay.setTextColor(Color.BLACK);
		}

		// highlight the current day
		if (listGridCellCal[1].equals("BLUE")) {
			if (dd == getCurrentDayOfMonth() && mm == (getCurrentMonth() + 1) && yy == getCurrentYear()) {
				gridcell.setTextColor(Color.BLACK);
				gridcell.setBackgroundResource(R.drawable.calendar_cell_today);
				lunarDay.setTextColor(Color.BLACK);

			} else {
				gridcell.setTextColor(Color.BLACK);
				lunarDay.setTextColor(Color.BLACK);
			}
		}

		if (listGridCellCal[1].equals("GREEN")) {
			if (dd == getCurrentDayOfMonth() && mm == (getCurrentMonth() + 1)
					&& yy == getCurrentYear()) {

				gridcell.setBackgroundResource(R.drawable.calendar_cell_today);
				gridcell.setTextColor(_context.getResources().getColor(R.color.green));
				lunarDay.setTextColor(_context.getResources().getColor(R.color.green));

			} else {
				gridcell.setTextColor(_context.getResources().getColor(R.color.green));
				lunarDay.setTextColor(_context.getResources().getColor(R.color.green));
			}
		}

		if (listGridCellCal[1].equals("RED")) {
			if (dd == getCurrentDayOfMonth() && mm == (getCurrentMonth() + 1)
					&& yy == getCurrentYear()) {

				gridcell.setBackgroundResource(R.drawable.calendar_cell_today);
				gridcell.setTextColor(Color.RED);
				lunarDay.setTextColor(Color.RED);

			} else {
				gridcell.setTextColor(Color.RED);
				lunarDay.setTextColor(Color.RED);
			}
		}
		
		// number of event each day
		eventsPerMonthMap = numberOfEventsPerDayMap(dd, mm, yy);
		if (!eventsPerMonthMap.isEmpty()) {
			if (eventsPerMonthMap.containsKey(listGridCellCal[0])) {
				gridcell.setBackgroundResource(R.drawable.calendar_cell_eventday);
			}
		}
		return row;
	}

	@Override
	public void onClick(View view) {
		String tag = (String) view.getTag();// dd/mm
		StringTokenizer token = new StringTokenizer(tag, "/");
		int dd = 0, mm = 0, yy = 0;

		while (token.hasMoreTokens()) {
			dd = Integer.parseInt(token.nextToken());
			mm = Integer.parseInt(token.nextToken());
			yy = Integer.parseInt(token.nextToken());
		}
		try {
			ArrayList<Festival> eventByDate = _festivalManager.searchByDate(dd, mm, yy);
			if (eventByDate.size() != 0) {
				Intent intent = new Intent(_context, FestivalActivity.class);
				intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				Bundle bundle = new Bundle();
				bundle.putSerializable("list", eventByDate);
				bundle.putString("tag", "fromCalendar");
				intent.putExtras(bundle);
				_context.startActivity(intent);
			}

		} catch (Exception ex) {
			Toast.makeText(_context, ex.getMessage(), Toast.LENGTH_LONG).show();
		}
	}

	public int getCurrentDayOfMonth() {
		return currentDayOfMonth;
	}

	public void setCurrentDayOfMonth(int currentDayOfMonth) {
		this.currentDayOfMonth = currentDayOfMonth;
	}

	public int getCurrentMonth() {
		return currentMonth;
	}

	public void setCurrentMonth(int currentMonth) {
		this.currentMonth = currentMonth;
	}

	public int getCurrentYear() {
		return currentYear;
	}

	public void setCurrentYear(int currentYear) {
		this.currentYear = currentYear;
	}

	public int getCurrentWeekDay() {
		return currentWeekDay;
	}

	public void setCurrentWeekDay(int currentWeekDay) {
		this.currentWeekDay = currentWeekDay;
	}

}